/**
 * This class have the rules to calculate amounts owed
 */

package com.src.uniandes.ecos.tsp.creditscore.algorithm;

import com.src.uniandes.ecos.tsp.creditscore.entity.ClienteProducto;
import com.src.uniandes.ecos.tsp.creditscore.jpa.ClienteProductoJpaController;
import java.util.ArrayList;
import java.util.List;

/**
 *
 * @author Sandra Torres
 */
public class RulesAmountsOwed {
    /**
     * This constant represents the product type: loan.
     */
    public static final Integer LOAN = 2;

    /**
     * This constant represents the product type: credit card.
     */
    public static final Integer CREDIT_CARD = 1;

    /**
     * This constant represents the percent.
     */
    public static final Integer PERCENT = 100;

    /**
     * This enum represents the points and range for loan.
     */
    private enum Loan {
        /**
         * Points and range maximum.
         */
        MAX(30.0, 0.0),
        /**
         * Points and range medium high.
         */
        MEH(22.5, 30.0),
        /**
         * Points and range medium low.
         */
        MEL(15.0, 60.0),
        /**
         * Points and range minimum.
         */
        MIN(7.5, 90.0);

        /**
         * This method obtains the points.
         * @return The points
         */
        public double getPoints() {
            return points;
        }

        /**
         * This method obtains the range.
         * @return The range
         */
         public double getRange() {
            return range;
        }

        /**
         * Enum constructor.
         * @param point The points
         * @param rang The range
         */
        private Loan(final double point, final double rang) {
            points = point;
            range = rang;
        }

        /**
         * Points.
         */
        private double points;

        /**
         * Range.
         */
        private double range;
    }

    /**
     * This enum represents the points and range for credit card.
     */
    private enum CreditCard {
        /**
         * Points and range maximum.
         */
        MAX(30.0, 50.0),
        /**
         * Points and range minimum.
         */
        MIN(15.0, 100.0);

        /**
         * This method obtains the points.
         * @return The points
         */
        public double getPoints() {
            return points;
        }

        /**
         * This method obtains the range.
         * @return The range
         */
         public double getRange() {
            return range;
        }

        /**
         * Enum constructor.
         * @param point The points
         * @param rang The range
         */
        private CreditCard(final double point, final double rang) {
            points = point;
            range = rang;
        }

        /**
         * Points.
         */
        private double points;

        /**
         * Range.
         */
        private double range;
    }

    /**
     * Class constructor.
     */
    public RulesAmountsOwed() {
        super();
    }

    /**
     * This method obtains the points for amounts owed by client.
     * @param codigoCliente The client to calculate
     * @return Number of points for amounts owed
     */
    public final double getPointTotalDebt(final Integer codigoCliente) {
        double point = 0.0;
        int product = 0;
        final ClienteProductoJpaController controllerCliente =
                new ClienteProductoJpaController();
        List<ClienteProducto> listClienteProducto = new ArrayList<ClienteProducto>();
        ClienteProducto clientProduct;
        listClienteProducto = controllerCliente.findClienteProductoEntities(codigoCliente);
        for (int i = 0; i < listClienteProducto.size(); i++) {
            clientProduct = listClienteProducto.get(i);
            if (clientProduct != null && clientProduct.getProducto() != null
                    && clientProduct.getProducto().getTipCodigo() != null
                    && clientProduct.getProducto().getTipCodigo().getTipCodigo() != null) {
                if (clientProduct.getProducto().getTipCodigo().getTipCodigo().equals(LOAN)) {
                    point = point + getPointLoan(clientProduct);
                    product = product + 1;
                } else {
                    if (clientProduct.getProducto().getTipCodigo().getTipCodigo().equals(CREDIT_CARD)) {
                        point = point + getPointCreditCard(clientProduct);
                        product = product + 1;
                    }
                }
            }
        }
        if (product != 0) {
            point = point / product;
        }
        return point;
    }

    /**
     * This method obtains the points for amounts owed by client of loan.
     * @param clientProduct The product to calculate
     * @return Number of points for amounts owed of loan
     */
    private double getPointLoan(final ClienteProducto clientProduct) {
        double point = 0.0;
        if (clientProduct != null && clientProduct.getClpSaldeu() != null && clientProduct.getClpValdes() != null) {
            final double overall = clientProduct.getClpValdes().doubleValue()
                    * (Math.pow((1 + (clientProduct.getClpTasint().doubleValue()/PERCENT)), clientProduct.getClpMesamo()));
            final double amountOwed = clientProduct.getClpSaldeu().doubleValue() * PERCENT / overall;
            if (amountOwed >= Loan.MAX.getRange() && amountOwed <= Loan.MEH.getRange()) {
                point = Loan.MAX.getPoints();
            } else {
                if (amountOwed > Loan.MEH.getRange() && amountOwed <= Loan.MEL.getRange()) {
                    point = Loan.MEH.getPoints();
                } else {
                    if (amountOwed > Loan.MEL.getRange() && amountOwed <= Loan.MIN.getRange()) {
                        point = Loan.MEL.getPoints();
                    } else {
                        if (amountOwed > Loan.MIN.getRange()) {
                            point = Loan.MIN.getPoints();
                        }
                    }
                }
            }
        }
        return point;
    }

    /**
     * This method obtains the points for amounts owed by client of credit card.
     * @param clientProduct The product to calculate
     * @return Number of points for amounts owed of credit card
     */
    private double getPointCreditCard(final ClienteProducto clientProduct) {
        double point = 0.0;
        if (clientProduct != null && clientProduct.getClpCuputi() != null && clientProduct.getClpCupdis() != null) {
            final double amountOwed = clientProduct.getClpCuputi().doubleValue() * PERCENT / clientProduct.getClpCupdis().doubleValue();
            if (amountOwed >= 0.0 && amountOwed <= CreditCard.MAX.getRange()) {
                point = CreditCard.MAX.getPoints();
            } else {
                if (amountOwed > CreditCard.MAX.getRange() && amountOwed <= CreditCard.MIN.getRange()) {
                    point = CreditCard.MIN.getPoints();
                }
            }
        }
        return point;
    }
}